/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.MessageFormat;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.constants.CodeConstants;
import org.zhiqim.kernel.constants.SignConstants;

/**
 * 字符串扩展工具类
 * 1.继承Stringx类，实现基础的字符串工具功能
 * 2.创建Strings类，实现扩展的字符串工具功能
 *
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Strings")
public class Strings extends Stringx implements SignConstants, CodeConstants
{
    /************************************************************************/
    //字符串格式化
    /************************************************************************/
    
    /**
     * 格式化占位符，和format方法不同的是：只处理指定的占位符
     * 
     * @param pattern       模式， 比如 "您已成功注册到%s，用户名：%s，密码：%s，请登录..."
     * @param placeholder   占位符号 比如 "%s"
     * @param arguments     替换列表，比如 {"知启蒙","张三","111111"};
     * @return              格式化后的内容，例子的内容则为： "您已成功注册到知启蒙，用户名：张三，密码：111111，请登录..."
     */
    public static String formatPlaceholder(String pattern, String placeholder, Object... arguments)
    {
        if (pattern == null || arguments == null || arguments.length == 0)
            return pattern;
        
        String[] segmentArr = pattern.split(placeholder);
        if (segmentArr.length <= 1)
            return pattern;
        
        int len = segmentArr.length;
        StringBuilder strb = new StringBuilder();
        
        int i = 0;
        for (;(i<len-1 && i<arguments.length);i++)
        {
            strb.append(segmentArr[i]).append(arguments[i]);
        }
        
        for (int j=i;j<len;j++)
        {//后面的加上
            strb.append(segmentArr[j]);
        }
        
        return strb.toString();
    }
    
    /**
     * 格式化，支持{}转化为%s，再作format处理，（即：注意如果pattern中有%s,%d等也会生效）
     * 
     * @param pattern       模式，比如 "您已成功注册到{}，用户名：{}，密码：{}，请登录..."
     * @param arguments     参数列表，比如 ["知启蒙","张三","111111"];
     * @return              格式化后的内容，例子的内容则为： "您已成功注册到知启蒙，用户名：张三，密码：111111，请登录..."
     */
    public static String formats(String pattern, Object... arguments)
    {
        if (Validates.isEmptyBlank(pattern) || arguments == null || arguments.length == 0)
            return pattern;
        
        if (pattern.indexOf("{}") != -1)
            pattern = pattern.replaceAll("\\{\\}", "%s");
        
        return String.format(pattern, arguments);
    }
    
    /**
     * 格式化，采用MessageFormat.format方法按{0},{0,number,#.#}格式进行格式化得到最后数据
     * 
     * @param pattern       模式 比如 "您已成功注册到{0}，用户名：{1}，密码：{2}，请登录..."
     * @param arguments     参数表，比如 ["知启蒙","张三","111111"];
     * @return              替换后的内容，例子的内容则为： "您已成功注册到知启蒙，用户名：张三，密码：111111，请登录..."
     */
    public static String formatMessage(String pattern, Object... arguments)
    {
        return MessageFormat.format(pattern, arguments);
    }
    
    /**
     * 格式化，支持两种格式化，先作formats,再作formatMessage
     * 
     * @param pattern       模式，比如 "您已成功注册到{0}，用户名：{1}，密码：{2}，请登录..."
     * @param arguments     参数列表，比如 ["知启蒙","张三","111111"];
     * @return              格式化后的内容，例子的内容则为： "您已成功注册到知启蒙，用户名：张三，密码：111111，请登录..."
     */
    public static String formatTwo(String pattern, Object...arguments)
    {
        if (Validates.isEmptyBlank(pattern) || arguments == null || arguments.length == 0)
            return pattern;
        
        if (pattern.indexOf("{}") != -1)
            pattern = pattern.replaceAll("\\{\\}", "%s");
        
        //1.先作消息文本方案，对处理失败的认为不适用
        try{pattern = MessageFormat.format(pattern, arguments);}catch(IllegalArgumentException e){}
        
        //2.再作传统字符方案
        return String.format(pattern, arguments);
    }
    
    /**
     * 格式化空格，对多个空格转化为一个空格
     * 
     * @param s         要格式化的字符串
     * @return          多空格转为一个空格
     */
    public static String formatSpace(String s)
    {
        s = trim(s);
        
        StringBuilder strb = new StringBuilder();
        char lastChar = 0;
        for (int i=0;i<s.length();i++)
        {
            char c = s.charAt(i);
            if (c == _SPACE_ && lastChar == _SPACE_)
                continue;
            
            strb.append(c);
            lastChar = c;
        }
        
        return strb.toString();
    }
    
    /********************************************************/
    //以下创建字符串的和获取字符串字节数组方法
    /********************************************************/
    
    /** 生成UTF-8的字符串 */
    public static String newStringUTF8(byte[] data)
    {
        return newString(data, _UTF_8_C_);
    }
    
    /** 生成指定编码的字符串 */
    public static String newString(byte[] data, String encoding)
    {
        try{return data==null?null:new String(data, encoding);}catch (UnsupportedEncodingException e){return null;}
    }
    
    /** 生成指定编码的字符串 */
    public static String newString(byte[] data, Charset encoding)
    {
        return data==null?null:new String(data, encoding);
    }
    
    /** 获取UTF8的字节 */
    public static byte[] getBytesUTF8(String s)
    {
        return s.getBytes(_UTF_8_C_);
    }
    
    /** 获取GBK的字节 */
    public static byte[] getBytesGBK(String s)
    {
        return s.getBytes(_GBK_C_);
    }

    /** 获取ISO8859-1的字节 */
    public static byte[] getBytesISO88591(String s)
    {
        try{return s.getBytes(_ISO_8859_1_);}catch (UnsupportedEncodingException e){return null;}
    }
    
    /** 转换为字符串，=NULL时为空字符串 */
    public static String toString(Object o)
    {
        return (o == null)?_EMPTY_:String.valueOf(o);
    }
    
    /** 转换为字符串，=NULL时为缺省值 */
    public static String toString(Object o, String dv)
    {
        return (o == null)?dv:String.valueOf(o);
    }
    
    /** 转换为布尔型，支持[true|false|yes|no|1|0|on|ff] */
    public static boolean toBooleanWide(String s, boolean dv)
    {
        if (s == null)
            return dv;
        else if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("on"))
            return true;
        else if (s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no") || s.equalsIgnoreCase("0")  || s.equalsIgnoreCase("off"))
            return false;
        else
            return dv;
    }
    
    /** 转换为布尔型，支持[true|false|yes|no|1|0|on|ff] */
    public static boolean toBooleanWide(String s)
    {
        Asserts.notNull(s);

        if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("on"))
            return true;
        else if (s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no") || s.equalsIgnoreCase("0")  || s.equalsIgnoreCase("off"))
            return false;
        else
            throw Asserts.exception("字符串宽泛式转为布尔型时值不在[true|false|yes|no|1|0|on|ff]规范内");
    }
    
    
    /**
     * 字符串(unicode)转为UTF-8的字节数组，各语言通用
     * 
     * @param str   字符串unicode双字节
     * @return      字节数组，单双三四字节转换
     */
    public static byte[] toUTF8(String str)
    {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        for (int i=0;i<str.length();i++)
        {
            char c = str.charAt(i);
            if (c <= 0x7F)
            {//0-127 单字节 7 bits
                out.write(c);
            }
            else if (c <= 0x7FF)
            {//128-2047 双字节 11 bits
                out.write(0xC0 | ((c >> 6) & 0x1F));
                out.write(0x80 | (c & 0x3F));
            }
            else if (c <= 0xFFFF)
            {//2048-65535 三字节 16 bits
                out.write(0xE0 | ((c >> 12) & 0x0F));
                out.write(0x80 | ((c >> 6) & 0x3F));
                out.write(0x80 | (c & 0x3F));
            }
            else
            {//65535- 四字节  21 bits
                out.write(0xF0 | (c >> 18));
                out.write(0x80 | ((c >> 12) & 0x3F));
                out.write(0x80 | ((c >> 6) & 0x3F));
                out.write(0x80 | (c & 0x3F));
            }
        }
        
        return out.toByteArray();
    }
    
    /********************************************************/
    //以下字符串扩展使用方法
    /********************************************************/
    
    /** 首字母大写 */
    public static String toUpperFirstChar(String str)
    {
        if (str == null)
            return null;
        
        str = trim(str);
        if (str.length() == 0)
            return _EMPTY_;
        
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
    
    /** 截取索引后面的字符串 */
    public static String indexOfString(String str, String indexOf)
    {
        if (str == null || indexOf == null || str.indexOf(indexOf) == -1)
            return str;
        
        int ind = str.indexOf(indexOf);
        return str.substring(ind+indexOf.length());
    }
    
    /** 从后面截取索引后面的字符串 */
    public static String lastIndexOfString(String str, String indexOf)
    {
        if (str == null || indexOf == null || str.lastIndexOf(indexOf) == -1)
            return str;
        
        int ind = str.lastIndexOf(indexOf);
        return str.substring(ind+indexOf.length());
    }
    
    /** 获取按含unicode的长度 */
    public static int lengthUnicode(String s)
    {
        if (s == null || s.length() ==0)
            return 0;
        
        int len = 0;
        for (int i=0;i<s.length();i++)
        {
            if ((int) s.charAt(i) > 127)
                len += 2;
            else
                len += 1;
        }
        return len;
    }
    
    /** 长度还剩多少字节 */
    public static int lengthUnicodeRemain(String s, int maxLength)
    {
        return maxLength - lengthUnicode(s);
    }
    
    /** 获取按127前长度为3，127后长度为5，计算得的长度 */
    public static int lengthUnicode35(String s)
    {
        if (s == null || s.length() ==0)
            return 0;
        
        int len = 0;
        for (int i=0;i<s.length();i++)
        {
            if ((int) s.charAt(i) > 127)
                len += 5;
            else
                len += 3;
        }
        return len;
    }

    /**
     * 截取字符串，从开头的长度
     * 
     * @param s             字符串
     * @param beginIndex    开始位置
     * @param length        长度
     * @return              从0的length
     */
    public static String substr(String s, int length)
    {
        return substr(s, 0, length);
    }
    
    /**
     * 截取字符串，指定长度
     * 
     * @param s             字符串
     * @param beginIndex    开始位置
     * @param length        长度
     * @return              从beginIndex的length
     */
    public static String substr(String s, int beginIndex, int length)
    {
        if (s == null)
            return s;
        
        int endIndex = beginIndex + length;
        return s.length() < endIndex?s.substring(beginIndex):s.substring(beginIndex, endIndex);
    }
    
    /**
     * 截取长度，指定汉字长度
     * 
     * @param str   源串
     * @param len   汉字长度
     * @return      截取后字母串，超长用...代替最后一个汉字
     */
    public static String substringLen(String str, int len)
    {
        if(Validates.isEmpty(str))
            return _EMPTY_;
        
        len = len * 5;//汉字位*5，再计算
        int length = 0;int ind = 0;
        for (int i=0;i<str.length();i++)
        {
            if ((int) str.charAt(i) > 127)
                length += 5;//汉字和字母宋体比例大概是5:3，即3个汉字和5个字母占位相当
            else
                length += 3;
            
            ind = i+1;
            if (length >= len)
                break;
        }
        
        if (ind < str.length())
            str = str.substring(0, ind-1) + "...";
        else
            str = str.substring(0, ind);
        
        return str;
    }
    
    /** 验证startsWith */
    public static boolean startsWith(String s, String ... prefixs)
    {
        Asserts.notNull(s, "s");
        Asserts.notNull(prefixs);
        
        for (String prefix : prefixs)
        {
            if (startsWith(s, prefix))
                return true;
        }
        
        return false;
    }
    
    /** 验证endsWith */
    public static boolean endsWith(String s, String ... suffixs)
    {
        Asserts.notNull(s, "s");
        Asserts.notNull(suffixs);
        
        for (String suffix : suffixs)
        {
            if (endsWith(s, suffix))
                return true;
        }
        
        return false;
    }

    /** 忽略大小写验证startsWith */
    public static boolean startsWithIgnoreCase(String s, String prefix)
    {
        if (prefix == null)
            return true;
        
        if (s == null || s.length() < prefix.length())
            return false;
        
        return s.toLowerCase().startsWith(prefix.toLowerCase());
    }
    
    /** 忽略大小写验证endsWith */
    public static boolean endsWithIgnoreCase(String s, String suffix)
    {
        if (suffix == null)
            return true;
        
        if (s == null || s.length() < suffix.length())
            return false;
        
        return s.toLowerCase().endsWith(suffix.toLowerCase());
    }
    
    /********************************************************/
    //以下获取字符串的前缀补位方法
    /********************************************************/
    
    /** 后置补齐，通过给定初始str,和前置char,得到给定长度的值, 通常用于前补0等 */
    public static String suffixLen(String value, int len, char suffix)
    {
        StringBuilder strb = new StringBuilder(value);
        for (int i=0;i<len;i++)
        {
            strb.append(suffix);
        }

        return strb.substring(0, len);
    }
    
    /** 后置补齐，通过给定初始int,和前置char,得到给定长度的值, 通常用于前补0等 */
    public static String suffixLen(int value, int len, char suffix)
    {
        StringBuilder strb = new StringBuilder(20).append(value);
        for (int i=0;i<len;i++)
        {
            strb.append(suffix);
        }

        return strb.substring(0, len);
    }
    
    /** 后置补齐，通过给定初始long,和前置char,得到给定长度的值, 通常用于前补0等 */
    public static String suffixLen(long value, int len, char suffix)
    {
        StringBuilder strb = new StringBuilder(38).append(value);
        for (int i=0;i<len;i++)
        {
            strb.append(suffix);
        }

        return strb.substring(0, len);
    }
    
    /** 获取字符串的整型数字后缀，如ERR:012等取后十进制数字12  */
    public static int suffixInt(String str)
    {
        StringBuilder strb = new StringBuilder();
        for (int i=str.length()-1;i>=0;i--)
        {
            char c = str.charAt(i);
            if (c < '0' || c > '9')
                break;

            strb.append(c);
        }
        
        if (strb.length() == 0){
            return 0;
        }
        
        return Ints.toInt(strb.toString());
    }
    
    /** 前缀补零，得到给定长度的值,补足0 */
    public static String prefixZero(String str, int len)
    {
        return prefixLen(str, len, '0');
    }
    
    /** 前缀补齐，通过给定初始str,和前置char,得到给定长度的值, 通常用于前补0等 */
    public static String prefixLen(String value, int len, char prefix)
    {
        int vlen = value.length();
        if (vlen == len)
        {//相等原值返回
            return value;
        }
        else if (vlen > len)
        {//超长截取
            return value.substring(vlen - len);
        }
        
        //不够补足
        StringBuilder strb = new StringBuilder(len);
        for (int i=vlen;i<len;i++)
        {
            strb.append(prefix);
        }

        return strb.append(value).toString();
    }
    
    /** 前缀补一个零，用于月份日期前补零，如3月份补成03 */
    public static String prefixZeroOne(int value, int lte)
    {
        return (value <= lte)?new StringBuilder("0").append(value).toString():Integer.toString(value);
    }
    
    /** 前缀补齐，得到给定长度的值,补足0 */
    public static String prefixZero(int value, int len)
    {
        return prefixLen(value, len, '0');
    }
    
    /** 前缀补齐，通过给定初始int,和前置char,得到给定长度的值, 通常用于前补0等 */
    public static String prefixLen(int value, int len, char prefix)
    {
        int vlen = Ints.length(value);
        if (vlen == len)
            return Integer.toString(value);
        
        StringBuilder strb = new StringBuilder();
        if (vlen < len)
        {//补足长度
            for (int i=vlen;i<len;i++)
            {
                strb.append(prefix);
            }
        }
        
        return strb.append(value).substring(strb.length() - len);
    }
    
    /** 前缀补齐，得到给定长度的值,补足0 */
    public static String prefixZero(long value, int len)
    {
        return prefixLen(value, len, '0');
    }
    
    /** 前缀补齐，通过给定初始int,和前置char,得到给定长度的值, 通常用于前补0等 */
    public static String prefixLen(long value, int len, char prefix)
    {
        int vlen = Longs.length(value);
        if (vlen == len)
            return Long.toString(value);
        
        StringBuilder strb = new StringBuilder();
        if (vlen < len)
        {//增加差的长度
            for (int i=vlen;i<len;i++)
            {
                strb.append(prefix);
            }
        }
        
        return strb.append(value).substring(strb.length() - len);
    }
    
    /** 获取字符串的整型数字前缀，如12px,122 str等取前数字 */
    public static int prefixInt(String str)
    {
        boolean isNon = '-' == str.charAt(0);
        if (isNon){
            str = str.substring(1);
        }
           
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<str.length();i++)
        {
            char c = str.charAt(i);
            if (c < '0' || c > '9')
                break;

            strb.append(c);
        }
        
        if (strb.length() == 0){
            return 0;
        }
        
        int num = Ints.toInt(strb.toString());
        return isNon?-num:num;
    }
    
    /** 获取字符串的浮点型数字前缀，如12.3px,122 str等取前数字 */
    public static float prefixFloat(String str)
    {
        boolean isNon = '-' == str.charAt(0);
        if (isNon){
            str = str.substring(1);
        }
           
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<str.length();i++)
        {
            char c = str.charAt(i);
            if ((c < '0' || c > '9') && c != '.')
                break;

            strb.append(c);
        }
        
        if (strb.length() == 0){
            return 0;
        }
        
        //排除第二个点后面的数字
        String prefix = strb.toString();
        int ind = prefix.indexOf(".");
        if (ind != -1){
            int ind2 = prefix.indexOf(".", ind+1);
            if (ind2 != -1)
                prefix = prefix.substring(0, ind2);
        }
        
        //前面的可能的0，parseFloat会忽略
        float num = Float.parseFloat(prefix);
        return isNon?-num:num;
    }
    
    /********************************************************/
    //以下获取字符串的出现的次数方法
    /********************************************************/
    
    /** 获取一个字符在字符串出现的次数 */
    public static int getTimes(String src, char c)
    {
        int times = 0;
        for (int i=0;i<src.length();i++)
        {
            if (c == src.charAt(i))
                times++;
        }
        
        return times;
    }
    
    /** 获取一个字符在字符串出现的次数，忽略最前和最后两个 */
    public static int getTimesIgnoreFirstLast(String src, char c)
    {
        int times = 0;
        for (int i=1;i<src.length()-1;i++)
        {
            if (c == src.charAt(i))
                times++;
        }
        
        return times;
    }

    /** 获取一个字符串在另字符串出现的次数 */
    public static int getTimes(String src, String str)
    {
        int times = 0;
        if (src == null || str == null)
            return times;
        
        int len = src.length();
        int timelen = str.length();
        if (len < timelen)
            return times;
        
        while(true)
        {
            int ind = src.indexOf(str);
            if (ind == -1)
                return times;
            
            times++;
            src = src.substring(ind+timelen);
        }
    }
    
    /** 判断起始分行符数，Windows(\r\n为2)，Mac(\r)或Linux(\n)为1，0表示没有\r或\n开头 */
    public static int getStartsWithBrNum(String content)
    {
        if (content.startsWith(_BR_))
            return 2;
        else if (content.startsWith(_LR_) || content.startsWith(_LN_))
            return 1;
        else
            return 0;
    }
    
    /** 是否包含乱码数 */
    public static int getMessyCodeNum(String s)
    {
        if (isEmpty(s))
            return 0;
        
        int num = 0;
        for (int i=0;i<s.length();i++) 
        {
            if ((int)s.charAt(i) == 0xFFFD) 
                num++;
        }
        
        return num;
    }
    
    /********************************************************/
    //以下整理字符串的方法
    /********************************************************/

    
    /** 去除前后空白，如果字符串=null，则返回指定的缺省值，支持去除中文空格12288和BOM65279 */
    public static String trim(String s, String defaultValue)
    {
        return (s == null)?defaultValue:trim(s);
    }
    
    /** 去除前后空白，如果字符串=null||isEmpty，则返回指定的缺省值，支持去除中文空格12288和BOM65279 */
    public static String trimEmpty(String s, String defaultValue)
    {
        return (s == null || s.isEmpty())?defaultValue:trim(s);
    }
    
    /** 去除前后空白，如果字符串=null||isEmptyBlank，则返回指定的缺省值，支持去除中文空格12288和BOM65279 */
    public static String trimEmptyBlank(String s, String defaultValue)
    {
        return (Validates.isEmptyBlank(s))?defaultValue:trim(s);
    }
    
    /** 删除字符串前面的空白,直到出现内容，支持去除中文空格12288和BOM65279 */
    public static String trimLeft(String s)
    {
        if (Validates.isEmpty(s))
            return s;
        
        int len = s.length(), i = 0;
        while ((i < len) && Validates.isWhitespace(s.charAt(i)))
            i++;
        return (i>0)?s.substring(i):s;
    }
    
    /** 删除字符串前面的一个BR，可能是\r,\n或\r\n */
    public static String trimLeftOneBR(String s)
    {
        if (Validates.isEmpty(s))
            return s;
        
        char c = s.charAt(0);
        if (c != _LF_ && c != _CR_)
            return s;
        
        if (c == _LF_)
            return s.substring(1);
        
        //第一个字符是\r的，检查第二个是不是\n
        if (s.length() > 1 && s.charAt(1) == _LF_)
            return s.substring(2);
        else
            return s.substring(1);
    }
    
    /** 删除字符串后面的空白,直到出现内容，支持去除中文空格12288和BOM65279 */
    public static String trimRight(String s)
    {
        if (Validates.isEmpty(s))
            return s;
        
        int len = s.length(), i = len-1;
        while ((i > 0) && Validates.isWhitespace(s.charAt(i)))
            i--;
        return (i<len-1)?s.substring(0, i+1):s;
    }
    
    /** 删除s中最后可能的多个c字符，如/home/zhiqim////删除/得到结果为/home/zhiqim */
    public static String trimRight(String s, char c)
    {
        if (Validates.isEmpty(s))
            return s;
        
        int len = s.length(), i = len-1;
        while (i > 0 && s.charAt(i) == c)
            i--;
        
        return (i<len-1)?s.substring(0, i+1):s;
    }
    
    /** 删除前后缀字符串，如果存在的话 */
    public static String trim(String s, String prefix, String suffix)
    {
        if (Validates.isEmpty(s))
            return s;
        
        if (!Validates.isEmpty(prefix) && s.startsWith(prefix))
            s = s.substring(prefix.length());
        
        if (!Validates.isEmpty(suffix) && s.endsWith(suffix))
            s = s.substring(0, s.length()-suffix.length());
        
        return s;
    }
    
    /** 删除前缀字符串 */
    public static String trimLeft(String s, String prefix)
    {
        if (Validates.isEmpty(s) || Validates.isEmpty(prefix))
            return s;
        
        if (!s.startsWith(prefix))
            return s;
        
        return s.substring(prefix.length());
    }
    
    /** 删除最后的后缀字符串 */
    public static String trimRight(String s, String suffix)
    {
        if (Validates.isEmpty(s) || Validates.isEmpty(suffix))
            return s;
        
        if (!s.endsWith(suffix))
            return s;
        
        return s.substring(0, s.length()-suffix.length());
    }
    
    /** 删除最后的后缀字符串 */
    public static void trimRight(StringBuilder strb, String suffix)
    {
        if (strb == null || Validates.isEmpty(suffix) || strb.length() < suffix.length())
            return;
        
        String end = strb.substring(strb.length() - suffix.length());
        if (suffix.equals(end))
            strb.setLength(strb.length() - suffix.length());
    }
    
    /********************************************************/
    //以下删除字符中指定的字符方法
    /********************************************************/
    
    /**
     * 删除s中所有空白 (包括空格以下(0x00-0x20)之间的所有字符,包括\t,\r,\n,\b等)
     * 
     * 举例: s = " a\tb\rc d ";得到结果是:returnString = "abcd";
     * @param s 原字符串
     * @return 删除空白之后的字符串
     */
    public static String removeAllBlank(String s)
    {
        if (Validates.isEmpty(s))
            return s;
        
        StringBuilder strb = new StringBuilder();
        for (int i=0;i<s.length();i++)
        {
            char c = s.charAt(i);
            if (Validates.isWhitespace(c))
                continue;
            
            strb.append(c);
        }
        
        return strb.toString();
    }
    
    /** 删除可能的第一个分隔符左边的所有字符，如org.zhiqim.example，删除后得到zhiqim.example */
    public static String removeLeftByFirst(String s, String separator)
    {
        if (Validates.isEmptyBlank(s))
            return _EMPTY_;

        s = s.trim();
        int pos = s.indexOf(separator);
        if (pos == -1)
            return s;
        
        return s.substring(pos + separator.length());
    }
    
    /** 删除可能的最后一个分隔符左边的所有字符，如org.zhiqim.example，删除后得到example */
    public static String removeLeftByLast(String s, String separator)
    {
        if (Validates.isEmptyBlank(s))
            return _EMPTY_;

        s = s.trim();
        int pos = s.lastIndexOf(separator);
        if (pos == -1)
            return s;
        
        return s.substring(pos + separator.length());
    }
    
    /** 删除可能的第一个分隔符右边的所有字符，如org.zhiqim.example，删除后得到org */
    public static String removeRightByFirst(String s, String separator)
    {
        if (Validates.isEmptyBlank(s))
            return _EMPTY_;

        s = s.trim();
        int pos = s.indexOf(separator);
        if (pos == -1)
            return s;
        else if (pos < 1)
            return _EMPTY_;
        else
            return s.substring(0, pos);
    }
    
    /** 删除可能的最后一个分隔符右边的所有字符，如org.zhiqim.example，删除后得到org.zhiqim */
    public static String removeRightByLast(String s, String separator)
    {
        if (Validates.isEmptyBlank(s))
            return _EMPTY_;

        s = s.trim();
        int pos = s.lastIndexOf(separator);
        if (pos == -1)
            return s;
        else if (pos < 1)
            return _EMPTY_;
        else
            return s.substring(0, pos);
    }
    
    /** 删除s中前缀字符串，如果有的话，功能同trimLeft */
    public static String removeStartsWith(String s, String startsWith)
    {
        return trimLeft(s, startsWith);
    }
    
    /** 删除s中后缀字符串，如果有的话，功能同trimRight */
    public static String removeEndsWith(String s, String endsWith)
    {
        return trimRight(s, endsWith);
    }
    
    /** 删除s中后缀字符串，如果有的话，功能同trimRight */
    public static void removeEndsWith(StringBuilder strb, String endsWith)
    {
        trimRight(strb, endsWith);
    }
    
    /**
     * 增加s中前缀字符串，如果需要的话
     * 
     * 举例 :  
     *  1) s == null, startsWith == null，返回null
     *  2) s == null, startsWith == ""，返回""
     *  3) s != null, startsWith == null || == ""，返回s
     *  4) s.startsWith(startsWith)，返回s
     *  5) !s.startsWith(startsWith)，返回startsWith + s
     * @param s 原字符串
     * @param startsWith 前缀字符串
     * @return 增加后的字符串
     */
    public static String addStartsWith(String s, String startsWith)
    {
        if (s == null)
            return startsWith;
        
        if (Validates.isEmpty(startsWith))
            return s;
        
        if (s.startsWith(startsWith))
            return s;
        
        return startsWith + s;
    }
    
    /**
     * 增加s中后缀字符串，如果需要的话
     * 
     * 举例 :  
     *  1) s == null, endsWith == null，返回null
     *  2) s == null, endsWith == ""，返回""
     *  3) s != null, endsWith == null || == ""，返回s
     *  4) s.endsWith(endsWith)，返回s
     *  5) !s.endsWith(endsWith)，返回s + endsWith
     * @param s         原字符串
     * @param endsWith  前缀字符串
     * @return          增加后的字符串
     */
    public static String addEndsWith(String s, String endsWith)
    {
        if (s == null)
            return endsWith;
        
        if (Validates.isEmpty(endsWith))
            return s;
        
        if (s.endsWith(endsWith))
            return s;
        
        return s + endsWith;
    }
    
    /** 增加新行\r\n */
    public static StringBuilder addNewLine(StringBuilder strb)
    {
        return strb.append(_BR_);
    }
    
    /** 增加多个双空格 */
    public static StringBuilder addTwoSpace(StringBuilder strb, int num)
    {
        for (int i=0;i<num;i++)
            strb.append(_TWO_);
        return strb;
    }
    
    /** 增加多个四空格 */
    public static StringBuilder addFourSpace(StringBuilder strb, int num)
    {
        for (int i=0;i<num;i++)
            strb.append(_FOUR_);
        
        return strb;
    }
    
    /** 增加多个制表符 */
    public static StringBuilder addTab(StringBuilder strb, int num)
    {
        for (int i=0;i<num;i++)
            strb.append(_TAB_);
        return strb;
    }
    
    /**
     * 多个空格间只保留一个空格 (包括空格以下(0x00-0x20)之间的所有字符,包括\t,\r,\n,\b等)
     * 
     * 举例: s = " a\tbc \r\nd ";得到结果是:returnString = "a bc d";
     * @param s         原字符串
     * @return          删除空白之后的字符串
     */
    public static String keepOneBlank(String s)
    {
        if (s == null)
            return s;
        
        if (Validates.isEmptyBlank(s))
            return _EMPTY_;
        
        s = Strings.trim(s);
        StringBuilder strb = new StringBuilder();
        for (int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);
            if (Validates.isWhitespace(c) && strb.charAt(strb.length() - 1) != _SPACE_)
            {//当前是空白符，上一个不是空格的，加空格
                strb.append(_SPACE_);
                continue;
            }
            
            strb.append(c);
        }
        
        return strb.toString();
    }
}
